﻿#include "FITKNastranAdaptorMAT1.h"

namespace Nastran
{
FITKNastranAdaptorMAT1::~FITKNastranAdaptorMAT1()
{
}

/*!
 *  Adapts material properties from a Nastran MAT1 file.
 *  return True if adaptation is successful, false otherwise.
 *
 * Checks for necessary data availability.
 * Extracts material properties from file content.
 * If 'MAT1*' format is detected, parses properties accordingly.
 * Otherwise, uses an alternative parsing method.
 * Obtains or creates a material object.
 * Configures density, elasticity, expansion, and damping behaviors.
 * Updates the material object with extracted properties.
 */
bool FITKNastranAdaptorMAT1::adaptR()
{
    if (nullptr == _caseData || nullptr == getReader() || _fileContentCache.isEmpty())
    {
        return false;
    }

    int fileMID = 0;
    double fileE = 0;
    double fileNU = 0;
    double fileRHO = 0;
    double fileA = 0;
    double fileTREF = 0;
    double fileGE = 0;
    QString line = _fileContentCache.head();

    if (line.startsWith("MAT1*"))
    {
        // TODO format error process, but now we don't have enough infotmation
        if (_fileContentCache.size() < 2)
        {
            getReader()->consoleMessage(3, "wrong MAT format");
            return false;
        }

        fileMID = line.mid(8 + 16 * 0, 16).toInt();
        fileE = line.mid(8 + 16 * 1, 16).toDouble();
        fileNU = line.mid(8 + 16 * 3, 16).toDouble();
        fileRHO = _fileContentCache[1].mid(8 + 16 * 0, 16).toDouble();
        fileA = _fileContentCache[1].mid(8 + 16 * 1, 16).toDouble();
        fileTREF = _fileContentCache[1].mid(8 + 16 * 2, 16).toDouble();
        fileGE = _fileContentCache[1].mid(8 + 16 * 3, 16).toDouble();
    }
    else
    {
        // TODO format error process, but now we don't have enough infotmation

        fileMID = line.mid(8 * 1, 8).toInt();
        fileE = line.mid(8 * 2, 8).toDouble();
        fileNU = line.mid(8 * 4, 8).toDouble();
        fileRHO = line.mid(8 * 5, 8).toDouble();
        fileA = line.mid(8 * 6, 8).toDouble();
        fileTREF = line.mid(8 * 7, 8).toDouble();
        fileGE = line.mid(8 * 8, 8).toDouble();
    }

    Interface::FITKAbaMaterial *materialPtr = nullptr;

    Interface::FITKMaterialManager *materialManager = _caseData->getMaterialManager();

    if (nullptr == materialManager)
    {
        getReader()->consoleMessage(3, "nullptr error for material manager");
        return false;
    }
    else
    {
        materialPtr = dynamic_cast<Interface::FITKAbaMaterial *>(
            _caseData->getMaterialManager()->getDataByName(QString::number(fileMID)));
    }

    if (nullptr == materialPtr)
    {
        materialPtr = new Interface::FITKAbaMaterial();
        materialPtr->setDataObjectName(QString::number(fileMID));
        _caseData->getMaterialManager()->appendDataObj(materialPtr);
    }
    else
    {
        getReader()->consoleMessage(
            2, QString("The material %1 already exists, now will cover it").arg(materialPtr->getDataObjectName()));
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Density);

    Interface::FITKAbaMaterialDensity *densityBehavior = dynamic_cast<Interface::FITKAbaMaterialDensity *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Density));

    if (nullptr != densityBehavior)
    {
        densityBehavior->setMassDensity(fileRHO);
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Elastic);
    Interface::FITKAbaMaterialElastic *materialBevior = dynamic_cast<Interface::FITKAbaMaterialElastic *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Elastic));

    if (nullptr != materialBevior)
    {
        materialBevior->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::IsoTropic);
        materialBevior->setIsotropicYoungsModulus(fileE);
        materialBevior->setIsotropicPoissonRatio(fileNU);
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Expansion);
    Interface::FITKAbaMaterialExpansion *expensionBehavior = dynamic_cast<Interface::FITKAbaMaterialExpansion *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Expansion));

    if (nullptr != expensionBehavior)
    {
        expensionBehavior->setExpansionType(Interface::FITKAbaMaterialBehaviorEnum::Isotropic);
        expensionBehavior->setIsotropicTemperature(fileTREF);
        expensionBehavior->setIsoTropicExpansionCoeff(fileA);
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Damping);
    Interface::FITKAbaMaterialDamping *dampingBehavior = dynamic_cast<Interface::FITKAbaMaterialDamping *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Damping));

    if (nullptr != dampingBehavior)
    {
        dampingBehavior->setStructural(fileGE);
    }

    return true;
}

// Assigns the provided FITKDataCase object to the _caseData member variable.
void FITKNastranAdaptorMAT1::setCaseData(AbaqusData::FITKDataCase *caseData)
{
    _caseData = caseData;
}

// Set the file content cache for the FITKNastranAdaptorMAT1 class
void FITKNastranAdaptorMAT1::setFileContentCache(QQueue<QString> cache)
{
    // Assign the provided cache to the class's file content cache
    _fileContentCache = cache;
}

} // namespace Nastran